<script setup>
import { getStatus, taskStatus } from './components/errorCode'
import { api } from '@/api'
import { fnTimeToUse } from '../../../components/time/timeFormat'
import { downloadTheFile, sortCol, fnIsError } from './components'
import AddInspection from './addTask.vue'
import ResultDetailDialog from './resultDetailDialog.vue'
import { useI18n } from 'vue-i18n'
import { computed, h, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
import {
  CaretRightOutlined,
  CloseCircleOutlined,
  ContainerOutlined, DeleteOutlined,
  ExclamationCircleOutlined, PauseCircleOutlined, RedoOutlined,
  ReloadOutlined,
  SyncOutlined, VerticalAlignBottomOutlined
} from '@ant-design/icons-vue'
import { Modal } from 'ant-design-vue'

const { t } = useI18n()

const props = defineProps(['type'])

const searchTask = ref('')
const taskList = ref([])
const showTable = ref([])
const pagination = reactive({
  sort: null,
  total: 0,
  current: 1,
  pageSize: 10,
  showTotal: total => `${t('common.total', { count: total })}`,
  showSizeChanger: true,
  pageSizeOptions: ['10', '20', '30', '40'],
})
const tableState = reactive({
  loading: false,
  selectedRowKeys: [],
})

const taskColumns = computed(() => [
  {
    key: 'task_name',
    title: t('osManager.taskName'),
    dataIndex: 'task_name',
    sortable: 'custom',
  },
  {
    key: 'statusStr',
    title: t('osManager.status'),
    dataIndex: 'statusStr',
    sortable: 'custom',
  },
  {
    key: 'progress',
    title: t('osManager.progress'),
    dataIndex: 'progress',
  },
  {
    key: 'startTimeStr',
    title: t('osManager.startTime'),
    dataIndex: 'startTimeStr',
  },
  {
    key: 'excutionTime',
    title: t('osManager.executeTime'),
    dataIndex: 'excutionTime',
  },
  {
    key: 'operation',
    title: t('common.operation'),
    dataIndex: 'operation',
    width: '25%',
    align: 'center',
  },
])

const TEN_SECOND = 10 * 1000;
const ONE_MIN = 60 * 1000;

const taskExecutionStatusEnum = {
  '200': 'SUCCESS',
  '201': 'RUNNABLE',
  '202': 'RUNNING',
  '203': 'PAUSE',
  '204': 'CANCELED',
  '206': 'PARTIAL_PASSED',
  '207': 'TIMEOUT',
  '208': 'WAITING',
  '209': 'NO_DATA_REPORTED',
  '400': 'FAILED',
  '401': 'SERVER_RESTART',
  '402': 'RECOVER',
  '600': 'UNKNOWN',
}
let intervalTimer = null
const addDialogShow = ref(false)
const editRow = null

const checkTask = ref({})
const resultDialogShow = ref(false)

function fnSearchTask() {
  if (!searchTask.value.trim()) {
    showTable.value = taskList.value
    return
  }
  showTable.value = taskList.value.filter(item => item.task_name.indexOf(searchTask.value.trim()) > -1)
}

function fnSortChange(page, filters, sorter) {
  page.current && (pagination.current = page.current)
  page.pageSize && (pagination.pageSize = page.pageSize)
  if (!sorter.order) {
    // 没有排序则按照后台返回顺序展示
    pagination.sort = null
    showTable.value.sort(sortCol('task_id', sorter.order))
    return
  }
  pagination.sort = sorter
  if (sorter.column === 'statusStr') {
    showTable.value.sort(sortCol('status', sorter.order))
  } else {
    showTable.value.sort(sortCol(sorter.column, sorter.order))
  }
}

async function initPage() {
  const [_, res] = await api.fnGetTaskList(props.type)
  let isRunning = false;
  taskList.value = res.task_infos
    .map(item => {
      item.statusStr = taskExecutionStatusEnum[item.status] || t('common.none')
      item.progress = item.progress.toFixed(2) * 100
      item.progressStatus = item.progress < 100 ? 'warning' : 'success'
      if (item.progress < 100 ) {
        isRunning = true
      }
      if (item.status === taskStatus.fail.code || item.status === taskStatus.exception.code) {
        item.progressStatus = 'exception'
      }

      item.startTimeStr = item.start_time ? new Date(item.start_time).toLocaleString() : ''
      item.excutionTime = item.end_time ? fnTimeToUse(item.end_time - item.start_time) : ''
      return item
    })
    .reverse()
  refreshTimer(isRunning ? TEN_SECOND : ONE_MIN)
  fnSearchTask()
  if (pagination.sort) {
    fnSortChange({}, '', pagination.sort)
  }
}

function refreshTimer(time) {
  if (intervalTimer) {
    clearInterval(intervalTimer)
    intervalTimer = null
  }
  intervalTimer = setInterval(() => {
    initPage()
  }, time)
}

async function fnHandleSuccess(data) {
  await initPage()
}

async function fnExeTask(row, action) {
  const param = {
    task_id: row.task_id,
    action,
  }
  const [_, res] = await api.fnTaskAttention(param)
  await fnHandleSuccess(res)
}

async function fnOpenAddDialog() {
  addDialogShow.value = true
}

function fnCloseAddDialog(isSuccess) {
  if (isSuccess) {
    initPage()
    refreshTimer(10000)
  }
  addDialogShow.value = false
}

async function fnDownloadReport(row) {
  const [_, res] = await api.fnDownloadReportById(row.task_id)
  if (res.data.type === 'application/json') {
    return
  }
  downloadTheFile(res.data, `${row.name}.zip`)
}

function fnOpenResultDialog(row) {
  checkTask.value = row
  resultDialogShow.value = true
}

function fnCloseResultDialog() {
  resultDialogShow.value = false
}

function fnConfirm(message, callback) {
  Modal.confirm({
    title: t('osManager.note'),
    icon: h(ExclamationCircleOutlined),
    content: message,
    okType: 'danger',
    okText: t('osManager.ok'),
    onOk: async () => {
      try {
        callback()
      } catch (error) {
        message.error(error)
      }
    },
  })
}

function fnBatchDelete() {
  const selectList = tableState.selectedRowKeys
  if (!selectList.length) {
    fnConfirm(t('osManager.selectATask'), () => {}, false)
    return
  }
  fnConfirm(t('osManager.batchDeleteTaskTip'), async () => {
    const [_, res] = await api.fnBatchDeleteTask(selectList)
    tableState.selectedRowKeys = []
    await fnHandleSuccess(res)
  })
}

async function fnDeleteTask(row) {
  fnConfirm(t('osManager.deleteTaskTip'), async () => {
    const [_, res] = await api.fnDeleteTask(row.task_id)
    await fnHandleSuccess(res)
  })
}

function onSelectChange(selectedRowKeys) {
  tableState.selectedRowKeys = selectedRowKeys
}

onMounted(() => {
  console.log('...' + props.type)
  initPage()

  // 每隔60000毫秒获取一下列表数据
  intervalTimer = setInterval(() => {
    initPage()
  }, 60000)
})

onBeforeUnmount(() => {
  intervalTimer && clearInterval(intervalTimer)
})
</script>

<template>
  <a-row type="flex" justify="space-between">
    <a-col>
      <a-row type="flex" :gutter="8">
        <a-col>
          <a-input-search
            v-model:value="searchTask"
            :maxlength="40"
            :placeholder="t('osManager.enterTaskName')"
            @search="fnSearchTask"
          />
        </a-col>
      </a-row>
    </a-col>
    <a-row type="flex" :gutter="16">
      <a-col>
        <a-button type="primary" @click="fnOpenAddDialog">{{ t('osManager.createTask') }}</a-button>
      </a-col>
      <a-col>
        <a-button type="primary" @click="fnBatchDelete">{{ t('osManager.batchDelete') }}</a-button>
      </a-col>
      <a-col>
        <a-button type="primary" :icon="h(SyncOutlined)" @click="initPage"></a-button>
      </a-col>
    </a-row>
  </a-row>

  <a-table
    row-key="task_id"
    :columns="taskColumns"
    :data-source="showTable"
    :loading="tableState.loading"
    :pagination="pagination"
    :row-selection="{
      selectedRowKeys: tableState.selectedRowKeys,
      onChange: onSelectChange,
    }"
    @change="fnSortChange"
  >
    <template #bodyCell="{ record, column }">
      <div v-if="column.dataIndex === 'progress'" style="display: flex; align-items: center">
        <a-progress
          :percent="record[column.dataIndex]"
          :status="record['progressStatus']"
          :show-info="false"
          style="flex: 1"
        ></a-progress>
        <div style="width: 23px; text-align: end">{{ record[column.dataIndex] }}</div>
      </div>
      <template v-else-if="column.dataIndex === 'operation'">
        <div class="flex items-center justify-center">
          <a-tooltip placement="top">
            <template #title>
              <span>{{
                  record.status === '202'
                    ? t('execution.task.cancelExecute')
                    : record.end_time
                      ? t('execution.task.retry')
                      : t('execution.task.startExecute')
                }}</span>
            </template>
            <a-button
              size="small"
              type="text"
              @click="
                fnExeTask(record, record.status === '202' ? 'cancel' : record.end_time ? 'retry' : 'start')
              "
            >
              <template #icon>
                <PauseCircleOutlined v-if="record.status === '202'" />
                <RedoOutlined v-else-if="record.end_time" />
                <CaretRightOutlined v-else />
              </template>
            </a-button>
          </a-tooltip>
          <a-divider type="vertical" />
          <a-tooltip placement="top">
            <template #title>
              <div>{{ t('osManager.viewDetail') }}</div>
            </template>
            <a-button
              size="small"
              type="text"
              @click="fnOpenResultDialog(record)"
            >
              <ContainerOutlined/>
            </a-button>
          </a-tooltip>
          <a-divider type="vertical" />
          <a-tooltip placement="top">
            <template #title>
              <div>{{ t('osManager.downloadReport') }}</div>
            </template>
            <a-button
              size="small"
              type="text"
              :disabled="Number(record.status) !== taskStatus.success.code"
              @click="fnDownloadReport(record)"
            >
              <VerticalAlignBottomOutlined/>
            </a-button>
          </a-tooltip>
          <a-divider type="vertical" />
          <a-tooltip placement="top">
            <template #title>
              <div>{{ t('common.delete') }}</div>
            </template>
            <a-button size="small" type="text" @click="fnDeleteTask(record)">
              <DeleteOutlined/>
            </a-button>
          </a-tooltip>
        </div>
      </template>
      <span v-else>{{ record[column.dataIndex] ? record[column.dataIndex] : '--' }}</span>
    </template>
  </a-table>
  <AddInspection
    :isShow="addDialogShow"
    :type="props.type"
    @close="fnCloseAddDialog"
    ref="addDialog"
    :edit-row="editRow"
  ></AddInspection>
  <ResultDetailDialog
    :id="checkTask.task_id"
    :type="props.type"
    :name="checkTask.task_name"
    :is-show="resultDialogShow"
    :status="checkTask.status"
    @close="fnCloseResultDialog"
  ></ResultDetailDialog>
</template>

<style scoped>
:deep(.actionBtn) {
  padding: 4px 4px;
  border: 0;
  font-size: 14px;
}

</style>
